package com.xsomnus.java_basic.juc.queue;

import java.util.Comparator;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.SynchronousQueue;

/**
 * @author @xsomnus666_xiawenye★
 * @since 2019/7/23 0023 15:36
 * - 才需学也,学需静也/非淡泊无以明志，非宁静无以致远
 */
public class SyncQueueExample {

    static class SyncQueueProducer implements Runnable {

        protected BlockingQueue<Integer> blockingQueue;

        private Random random = new Random(1000);

        public SyncQueueProducer(BlockingQueue<Integer> blockingDeque) {
            this.blockingQueue = blockingDeque;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    final Integer uuid = random.nextInt(1999);
                    System.out.println("Put: " + uuid);
                    blockingQueue.put(uuid);
                    Thread.sleep(1_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    static class SyncQueueConsumer implements Runnable {

        protected BlockingQueue<Integer> blockingQueue;

        public SyncQueueConsumer(BlockingQueue<Integer> blockingQueue) {
            this.blockingQueue = blockingQueue;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    Integer data = blockingQueue.take();
                    System.out.println(Thread.currentThread().getName() + " take: " + data);
                    Thread.sleep(5_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    private static void testSynchronousQueue() {

        final BlockingQueue<Integer> blockingQueue = new SynchronousQueue<>();

        SyncQueueProducer producer = new SyncQueueProducer(blockingQueue);
        new Thread(producer).start();

        SyncQueueConsumer consumer1 = new SyncQueueConsumer(blockingQueue);
        SyncQueueConsumer consumer2 = new SyncQueueConsumer(blockingQueue);
        new Thread(consumer1).start();
        new Thread(consumer2).start();
    }

    private static void testPriorityBlockingQueue() {

        final BlockingQueue<Integer> blockingQueue = new PriorityBlockingQueue<>(15, Comparator.naturalOrder());

        SyncQueueProducer producer = new SyncQueueProducer(blockingQueue);
        new Thread(producer).start();

        SyncQueueConsumer consumer1 = new SyncQueueConsumer(blockingQueue);
        SyncQueueConsumer consumer2 = new SyncQueueConsumer(blockingQueue);
        new Thread(consumer1).start();
        new Thread(consumer2).start();
    }
    public static void main(String[] args) {
        testSynchronousQueue();
    }
}
